/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * 是一个接口，它描述了一个 Bean 实例的定义，包括属性值、构造方法值和继承自它的类的更多信息
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	/**
	 * 标准单例作用域的作用域标识符：“ singleton”。
	 * 请注意，扩展的bean工厂可能支持更多范围。
	 *
	 * @see #setScope
	 */
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

	/**
	 * 标准原型范围的范围标识符：“prototype”。
	 *
	 * @see #setScope
	 */
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


	/**
	 * 角色提示，指示{@code BeanDefinition}是应用程序的主要部分。 通常对应于用户定义的bean。
	 */
	int ROLE_APPLICATION = 0;

	/**
	 * Role hint indicating that a {@code BeanDefinition} is a supporting
	 * part of some larger configuration, typically an outer
	 * {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
	 * {@code SUPPORT} beans are considered important enough to be aware
	 * of when looking more closely at a particular
	 * {@link org.springframework.beans.factory.parsing.ComponentDefinition},
	 * but not when looking at the overall configuration of an application.
	 */

//	ROLE_SUPPORT =1实际上就是说，我这个Bean是用户的，是从配置文件中过来的。
	int ROLE_SUPPORT = 1;

	/**
	 * Role hint indicating that a {@code BeanDefinition} is providing an
	 * entirely background role and has no relevance to the end-user. This hint is
	 * used when registering beans that are completely part of the internal workings
	 * of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
	 */

//	ROLE_INFRASTRUCTURE = 2就是我这Bean是Spring自己的，和你用户没有一毛钱关系。
	int ROLE_INFRASTRUCTURE = 2;


	// 可修改的属性

	/**
	 * 设置此bean definition 的父 definition 的名称（如果有）。
	 */
	void setParentName(@Nullable String parentName);

	/**
	 * 返回此bean definition 的父 definition 的名称（如果有）。
	 */
	@Nullable
	String getParentName( );

	/**
	 * 指定该bean definition的 bean 类型名称
	 * 可以在bean factory后处理期间修改类名,通常将原始类名替换为其解析的变体
	 *
	 * @see #setParentName
	 * @see #setFactoryBeanName
	 * @see #setFactoryMethodName
	 */
	void setBeanClassName(@Nullable String beanClassName);

	/**
	 * 返回此Bean definition 的当前Bean类名称。
	 * <p>请注意，如果子定义从其父级继承/继承了该类名，则不必是在运行时使用的实际类名。
	 * 同样，这可能只是调用工厂方法的类，或者在调用工厂方法的工厂bean引用的情况下甚至可能为空。
	 * 因此，<i>不</ i>在运行时不要将其视为确定的bean类型，而仅将其用于单个bean定义级别的解析目的。
	 *
	 * @see #getParentName()
	 * @see #getFactoryBeanName()
	 * @see #getFactoryMethodName()
	 */
	@Nullable
	String getBeanClassName( );

	/**
	 * Override the target scope of this bean, specifying a new scope name.
	 *
	 * @see #SCOPE_SINGLETON
	 * @see #SCOPE_PROTOTYPE
	 */
	void setScope(@Nullable String scope);

	/**
	 * Return the name of the current target scope for this bean,
	 * or {@code null} if not known yet.
	 */
	@Nullable
	String getScope( );

	/**
	 * Set whether this bean should be lazily initialized.
	 * 如果{@code false}，则将在执行启动单例初始化的bean工厂启动时实例化bean。
	 */
	void setLazyInit(boolean lazyInit);

	/**
	 * Return whether this bean should be lazily initialized, i.e. not
	 * eagerly instantiated on startup. Only applicable to a singleton bean.
	 */
	boolean isLazyInit( );

	/**
	 * 设置该bean初始化依赖的bean的名称。 Bean工厂将确保首先初始化这些Bean。
	 */
	void setDependsOn(@Nullable String... dependsOn);

	/**
	 * Return the bean names that this bean depends on.
	 */
	@Nullable
	String[] getDependsOn( );

	/**
	 * 设置此bean是否是注入到其他bean的候选者
	 * 请注意，此标志旨在仅影响基于类型的自动装配。
	 * 它不会影响按名称的显式引用，即使指定的bean未标记为自动装配候选者，名称也将得到解析。
	 * 因此，如果名称匹配，按名称自动装配仍将注入Bean。
	 */
	void setAutowireCandidate(boolean autowireCandidate);

	/**
	 * 返回该bean是否是装配到其他bean的候选者
	 */
	boolean isAutowireCandidate( );

	/**
	 * 设置该bean是否是主要的装配候选者
	 */
	void setPrimary(boolean primary);

	/**
	 * Return whether this bean is a primary autowire candidate.
	 */
	boolean isPrimary( );

	/**
	 * 这是调用指定工厂方法的bean的名称。
	 *
	 * @see #setFactoryMethodName
	 */
	void setFactoryBeanName(@Nullable String factoryBeanName);

	/**
	 * Return the factory bean name, if any.
	 */
	@Nullable
	String getFactoryBeanName( );

	/**
	 * Specify a factory method, if any. This method will be invoked with
	 * constructor arguments, or with no arguments if none are specified.
	 * The method will be invoked on the specified factory bean, if any,
	 * or otherwise as a static method on the local bean class.
	 *
	 * @see #setFactoryBeanName
	 * @see #setBeanClassName
	 */
	void setFactoryMethodName(@Nullable String factoryMethodName);

	/**
	 * Return a factory method, if any.
	 */
	@Nullable
	String getFactoryMethodName( );

	/**
	 * 返回此bean的构造器参数
	 * <p>可以在bean工厂后处理期间修改返回的实例。
	 *
	 * @return the ConstructorArgumentValues object (never {@code null})
	 */
	ConstructorArgumentValues getConstructorArgumentValues( );

	/**
	 * 返回是否为此bean定义了构造函数参数值。
	 *
	 * @since 5.0.2
	 */
	default boolean hasConstructorArgumentValues( ) {
		return !getConstructorArgumentValues().isEmpty();
	}

	/**
	 * 返回要应用于新的bean实例的属性值。
	 * 可以在bean工厂后处理期间修改返回的实例。
	 *
	 * @return the MutablePropertyValues object (never {@code null})
	 */
	MutablePropertyValues getPropertyValues( );

	/**
	 * Return if there are property values values defined for this bean.
	 *
	 * @since 5.0.2
	 */
	default boolean hasPropertyValues( ) {
		return !getPropertyValues().isEmpty();
	}

	/**
	 * 设置init方法名称
	 *
	 * @since 5.1
	 */
	void setInitMethodName(@Nullable String initMethodName);

	/**
	 * Return the name of the initializer method.
	 *
	 * @since 5.1
	 */
	@Nullable
	String getInitMethodName( );

	/**
	 * 设置destroy方法名称
	 *
	 * @since 5.1
	 */
	void setDestroyMethodName(@Nullable String destroyMethodName);

	/**
	 * Return the name of the destroy method.
	 *
	 * @since 5.1
	 */
	@Nullable
	String getDestroyMethodName( );

	/**
	 * Set the role hint for this {@code BeanDefinition}. The role hint
	 * provides the frameworks as well as tools with an indication of
	 * the role and importance of a particular {@code BeanDefinition}.
	 *
	 * @see #ROLE_APPLICATION
	 * @see #ROLE_SUPPORT
	 * @see #ROLE_INFRASTRUCTURE
	 * @since 5.1
	 */
	void setRole(int role);

	/**
	 * Get the role hint for this {@code BeanDefinition}. The role hint
	 * provides the frameworks as well as tools with an indication of
	 * the role and importance of a particular {@code BeanDefinition}.
	 *
	 * @see #ROLE_APPLICATION
	 * @see #ROLE_SUPPORT
	 * @see #ROLE_INFRASTRUCTURE
	 */
	int getRole( );

	/**
	 * 设置此bean定义的可读描述。
	 *
	 * @since 5.1
	 */
	void setDescription(@Nullable String description);

	/**
	 * Return a human-readable description of this bean definition.
	 */
	@Nullable
	String getDescription( );


	// Read-only attributes

	/**
	 * 根据Bean类或其他特定的元数据返回此Bean definition的可解析类型。
	 * 通常可以在运行时合并的bean definition中完全解决此问题，而不必在配置时定义实例上完全解决。
	 *
	 * @return the resolvable type (potentially {@link ResolvableType#NONE})
	 * @see ConfigurableBeanFactory#getMergedBeanDefinition
	 * @since 5.2
	 */
	ResolvableType getResolvableType( );

	/**
	 * Return whether this a <b>Singleton</b>, with a single, shared instance
	 * returned on all calls.
	 *
	 * @see #SCOPE_SINGLETON
	 */
	boolean isSingleton( );

	/**
	 * Return whether this a <b>Prototype</b>, with an independent instance
	 * returned for each call.
	 *
	 * @see #SCOPE_PROTOTYPE
	 * @since 3.0
	 */
	boolean isPrototype( );

	/**
	 * Return whether this bean is "abstract", that is, not meant to be instantiated.
	 */
	boolean isAbstract( );

	/**
	 * 返回此bean definition 所来自的资源的描述（以在发生错误的情况下显示上下文）。
	 */
	@Nullable
	String getResourceDescription( );

	/**
	 * 返回原始的BeanDefinition，如果没有，则返回{@code null}。
	 * 允许获取修饰的bean definition（如果有）。
	 * <p>请注意，此方法返回直接发起者。 遍历发起者链以找到用户定义的原始BeanDefinition。
	 */
	@Nullable
	BeanDefinition getOriginatingBeanDefinition( );

}
